package com.generic.action.member;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.util.ServletContextAware;

import com.generic.dao.impl.ImageDao;
import com.generic.dao.impl.MemberDao;
import com.generic.ds.HibernateSession;
import com.generic.module.impl.Image;
import com.generic.module.impl.Member;
import com.generic.util.Constant;
import com.generic.util.FileUtil;
import com.generic.util.GraphicsUtil;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

@Namespace("/member")
@ParentPackage("member")
@InterceptorRefs({
	@InterceptorRef("jsonValidationWorkflowStack"),
	@InterceptorRef("authorizationStack")	
})
public class Photo extends ActionSupport implements ServletContextAware {

	private static final long serialVersionUID = -7204695240685544625L;
	private static final Log log = LogFactory.getLog(Photo.class);
	private ServletContext servletContext;
	private String photoName;
	private Long id;
	private List<Image> images;	
	private String ids;
	private String[] captions;
	private Long defaultId;
	private String[] tempImageNames;
	private String[] xywh;
	
	public String[] getXywh() {
		return xywh;
	}

	public void setXywh(String[] xywh) {
		this.xywh = xywh;
	}

	public String getImageFolder() {
		return Constant.IMAGE_TEMP;
	}

	public String[] getTempImageNames() {
		return tempImageNames;
	}

	public void setTempImageNames(String[] tempImageNames) {
		this.tempImageNames = tempImageNames;
	}

	public String getPhotoName() {
		return photoName;
	}

	public void setPhotoName(String photoName) {
		this.photoName = photoName;
	}

	public List<Image> getImages() {
		return images;
	}

	public Long getId() {
		return id;
	}

	public void setImages(List<Image> images) {
		this.images = images;
	}
	
	public String getIds() {
		return ids;
	}
	
	public String[] getCaptions() {
		return captions;
	}
	
	public Long getDefaultId() {
		return defaultId;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public void setIds(String ids) {
		this.ids = ids;
	}
	
	public void setCaptions(String[] captions) {
		this.captions = captions;
	}

	public void setDefaultId(Long defaultId) {
		this.defaultId = defaultId;
	}

	@Override
	public void setServletContext(ServletContext context) {
		this.servletContext = context;
	}
	
	public String execute() {
		Map<String, Object> session = ActionContext.getContext().getSession();
		Member member = (Member) session.get(Constant.SESSION_MEMBER);
		id = member.getId();
		
		try {
			File imgDir = new File(servletContext.getRealPath("/") + Constant.IMAGE_TEMP+id);
			if(imgDir != null && imgDir.isDirectory()) {
				// exclude the thumb.db file from the directory if any
				FilenameFilter fileFilter = new FilenameFilter() {
				    public boolean accept(File file, String name) {
				        return !name.endsWith(".db") ;
				    }
				};
				tempImageNames = imgDir.list(fileFilter);
			}
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return SUCCESS;
	}

	@Action(value="photo-save", results = {
			@Result(name = "input", location="../ajax-error.jsp"),
		    @Result(name = "success", location="../ajax-msg.jsp") })
	public String save() {
		if(tempImageNames == null || tempImageNames.length == 0) {
			return SUCCESS;
		}
		
		Map<String, Object> session = ActionContext.getContext().getSession();
		Member member = (Member)session.get(Constant.SESSION_MEMBER);
		id = member.getId();
		
		HibernateSession hs = new HibernateSession();
		try {
			hs.beginTransaction();
			
			// Create directory folder for the image file 
			File filePath = new File(servletContext.getRealPath("/") + Constant.IMAGE_PATH + id);
			if(!filePath.exists()) {
				filePath.mkdirs();
			}	
			
			// Create directory folder for image thumbnails 
			File filePath2 = new File(servletContext.getRealPath("/") + Constant.IMAGE_THUMB_PATH + id);
			if(!filePath2.exists()) {
				filePath2.mkdirs();
			}
			
			// Create directory folder for cover image 
			File filePath3 = new File(servletContext.getRealPath("/") + Constant.IMAGE_COVER_PATH + id);
			if(!filePath3.exists()) {
				filePath3.mkdirs();
			}
			
			ImageDao imageDao = new ImageDao(hs);
			for(int i=0; i<tempImageNames.length; i++) {
				String fileName = tempImageNames[i];				
				File fileSrc = new File(servletContext.getRealPath("/")+Constant.FILE_SEPARATOR+Constant.IMAGE_TEMP+id+Constant.FILE_SEPARATOR+fileName);
				File fileNew = new File(filePath, fileName);
				String fileExtension = fileName.substring(fileName.lastIndexOf(".")+1);
				
				// Save image meta data into database 
				Image image = new Image();
				image.setProfileId(id);
				image.setFileName(fileName);
				image.setSeq(i);
				if(!captions[i].equals("")) {
					image.setCaption(captions[i]);
				}
				imageDao.insertOrUpdate(image);
				
				// Save image 
				FileUtils.copyFile(fileSrc, fileNew);
				
				// Save image thumbnail 
				fileNew = new File(filePath2, fileName);
				BufferedImage img = ImageIO.read(fileSrc);
				BufferedImage bi = GraphicsUtil.getThumbnailSize(img);
				ImageIO.write(bi, fileExtension, fileNew);
				
				// Save cover image
				String[] imageProp = xywh[i].split(",");
				Integer x = Integer.parseInt(imageProp[0]);
				Integer y = Integer.parseInt(imageProp[1]);
				Integer w = Integer.parseInt(imageProp[2]);
				Integer h = Integer.parseInt(imageProp[3]);
				fileNew = new File(filePath3, fileName);
				bi = GraphicsUtil.getCoverSize(img.getSubimage(x,y,w,h));
				ImageIO.write(bi, fileExtension, fileNew);
			}
			
			hs.commitTransaction();
			addActionMessage("Success!");
		} catch (Exception e) {
			log.error(e.getMessage());
			hs.rollbackTransaction();
		} finally {
			hs.closeSession();
		}
		return SUCCESS;
	}
	
	@Action(value = "/photo-edit-page", results = {
		    @Result(name = "success", location="member/photo-edit-page.jsp") })
	public String editPage() {		
		/*HibernateSession hs = new HibernateSession();
		try {
			hs.beginTransaction();
			
			ImageDao imageDao = new ImageDao(hs);
			String[] ids = this.ids.split(",");
			String[] captions = this.captions.split(",");
			for(int i=0; i<ids.length; i++) {
				Image img = (Image)imageDao.find(Long.parseLong(ids[i]));
				img.setCaption(captions[i]);
				imageDao.insertOrUpdate(img);
			}
			
			hs.commitTransaction();
			addActionMessage("Success!");
		} catch (Exception e) {
			hs.rollbackTransaction(e);
		} finally {
			hs.closeSession();
		}*/
		return SUCCESS;
	}
		
	@Action(value = "/photo-delete", results = {
		    @Result(name = "success", location="ajax-msg.jsp") })
	public String delete() {
		Map<String, Object> session = ActionContext.getContext().getSession();
		Member member = (Member) session.get(Constant.SESSION_MEMBER);
		Long memberId = member.getId();
//		Long memberId = 1l;
		HibernateSession hs = new HibernateSession();
		try {
			hs.beginTransaction();
			
			ImageDao imageDao = new ImageDao(hs);
			String[] ids = this.ids.split(",");
			for (int i = 0; i < ids.length; i++) {
				Image img = (Image) imageDao.find(Long.parseLong(ids[i]));
				String fileName = img.getFileName();
				/* Delete image meta info from database */
				imageDao.delete(img);
				/* Delete image from file system */
				FileUtil.delete(servletContext.getRealPath("/") + Constant.IMAGE_PATH + memberId + Constant.FILE_SEPARATOR + fileName);
				/* Delete image thumbnail from file system */
				FileUtil.delete(servletContext.getRealPath("/") + Constant.IMAGE_THUMB_PATH + memberId + Constant.FILE_SEPARATOR + fileName);
			}
			
			hs.commitTransaction();
			addActionMessage("Success!");
		} catch (Exception e) {
			hs.rollbackTransaction();
			log.error(e.getMessage());
		} finally {
			hs.closeSession();
		}
		return SUCCESS;
	}
	
	@Action(value = "/photo-default", results = {
		    @Result(name = "success", location="ajax-msg.jsp") })
	public String defaultPhoto() {
		Map<String, Object> session = ActionContext.getContext().getSession();
		Member member = (Member) session.get(Constant.SESSION_MEMBER);
		Long memberId = member.getId();
//		Long memberId = 1l;
		HibernateSession hs = new HibernateSession();
		try {
			hs.beginTransaction();
			
			MemberDao memberDao = new MemberDao(hs);
			memberDao.setDefaultImage(memberId, Long.parseLong(ids));
			
			hs.commitTransaction();
			addActionMessage("Success!");
		} catch (Exception e) {
			hs.rollbackTransaction();
			log.error(e.getMessage());
		} finally {
			hs.closeSession();
		}
		return SUCCESS;
	}
	
	@Action(value = "photo-gallery", results = {
		    @Result(name = "success", location="photo-gallery.jsp") })
	public String photoGallery() {
		Map<String, Object> session = ActionContext.getContext().getSession();
		Member member = (Member) session.get(Constant.SESSION_MEMBER);
		Long memberId = member.getId();
		
		HibernateSession hs = new HibernateSession();
		try {
			ImageDao imageDao = new ImageDao(hs);			
			images = imageDao.getImages(memberId);
		} catch (Exception e) {
			hs.rollbackTransaction(e);
		} finally {
			hs.closeSession();
		}
		return SUCCESS;
	}
	/*
	@Action(value = "/profile-photo-save", results = {
			@Result(name = "input", location = "member/profile-photo-edit.jsp"),
		    @Result(name = "success", location = "member/profile-photo-edit.jsp") })
	public String profilePhotoSave() {
		Map<String, Object> session = ActionContext.getContext().getSession();
		Member member = (Member)session.get(Constant.SESSION_MEMBER);
		Long memberId = member.getId();
		
		HibernateSession hs = new HibernateSession();
		try {
			hs.beginTransaction();
			ImageDao imageDao = new ImageDao(hs);
			
			 Create directory folder for the image file 
			String dirPath = Constant.IMAGE_PATH + memberId;
			File filePath = new File(servletContext.getRealPath("/") + dirPath);
			filePath.mkdirs();
			
			 Create directory folder for the image thumbnail 
			dirPath = Constant.IMAGE_THUMBNAIL_PATH + memberId;
			File filePath2 = new File(servletContext.getRealPath("/") + dirPath);
			filePath2.mkdirs();
			
			Long seq = imageDao.getMaxId(memberId);
			for (int i = 0; i < uploads.length; i++) {
//				String fileName = uploadFileNames[i].replace(" ", "_");
				String fileExtension = uploadFileNames[i].substring(uploadFileNames[i].lastIndexOf(".")+1);
				String fileName = seq++ + "." + fileExtension;
				File file = new File(filePath, fileName);
				if (!file.exists()) {
					BufferedImage img = ImageIO.read(uploads[i]);
					 Save image 
					BufferedImage bi = GraphicsUtil.getStandardSize(img);
					ImageIO.write(bi, fileExtension, file);
					
					 Save image thumbnail 
					file = new File(filePath2, fileName);
					bi = GraphicsUtil.getThumbnailSize(img);
					ImageIO.write(bi, fileExtension, file);
					
					 Save image meta data into database 
					Image image = new Image();
					image.setProfileId(memberId);
					image.setFileName(fileName);
					imageDao.insertOrUpdate(image);
				}
			}
			 Set first image as the default image if it hasn't been set 
			if(member.getImageId() == null) {
				Long imageId = imageDao.getMinId(memberId);
				MemberDao memberDao = new MemberDao(hs);
//				memberDao.setDefaultImage(memberId, imageId);
				member.setImageId(imageId);
				memberDao.insertOrUpdate(member);
			}			
			
			hs.commitTransaction();
		} catch (Exception e) {
			hs.rollbackTransaction(e);
		} finally {
			hs.closeSession();
		}

		return SUCCESS;
	}*/
}
